package com.example.threadcode.higherLeverTwo.CyclicBarrierDemo;

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

public class CyclicBarrierDemo
{


   /**
    * 主线程创建2维浮点matrix数组,并初始化值.
    * 调用 dump方法就是遍历输出matrix数组所有值
    * 然后实例化Solver对象,这个对象创建单独的线程对matrix每行执行一个计算,
    * 最后调用dump将修该后的matrix输出
    */
   public static void main(String[] args)
   {
      float[][] matrix = new float[3][3];
      int counter = 0;
      for (int row = 0; row < matrix.length; row++) {
         for (int col = 0; col < matrix[0].length; col++){
            matrix[row][col] = counter++;
         }
      }
      dump(matrix);
      System.out.println();
      Solver solver = new Solver(matrix);
      System.out.println();
      dump(matrix);
   }

   static void dump(float[][] matrix)
   {
      for (int row = 0; row < matrix.length; row++)
      {
         for (int col = 0; col < matrix[0].length; col++){
            System.out.print(matrix[row][col] + " ");
         }
         System.out.println();
      }
   }
}


class Solver 
{
   final int N;
   final float[][] data;
   final CyclicBarrier barrier;

   class Worker implements Runnable 
   {
      int myRow;
      boolean done = false;

      Worker(int row) 
      { 
         myRow = row; 
      }

      boolean done()
      {
         return done;
      }

      void processRow(int myRow)
      {
         System.out.println("Processing row: " + myRow);
         for (int i = 0; i < N; i++)
            data[myRow][i] *= 10;
         done = true;
      }

      /**
       *  processRow方法一直执行,直到done返回true,它返回true意味着这条线程要往下执行完毕
       *  此时调用障碍线程的await方法使得线程等待而不向下执行.当最后一个线程进入等待,那么将触发障碍实例定义的回应动作
       */
      @Override
      public void run() 
      {
         while (!done()) 
         {
            processRow(myRow);

            try 
            {
               barrier.await();
            } 
            catch (InterruptedException ie) 
            {
               return;
            } 
            catch (BrokenBarrierException bbe) 
            {
               return;
            }
         }
      }
   }
   /**
    * 定义构造器.接收一个matrix参数.然后储存他的引用到data,还有他的行数存到N
    * 然后创建一个带有N个parties和对合并所有的行进入最终的matrix的回应动作的循环障碍对象
    * 最终這个构造器创建一个Worker线程,這个线程执行一个单独的runnable方法,這个方法负责在matrix处理一行
    * 然后Worker线程等待,直到所有的Worker线程执行完processRow进入等待.
    *
    */
   public Solver(float[][] matrix)
   {
      data = matrix;
      N = matrix.length;
      barrier = new CyclicBarrier(N,
                                  new Runnable() 
                                  {
                                     @Override
                                     public void run() 
                                     {
                                        mergeRows();
                                     }
                                  });
      for (int i = 0; i < N; ++i) {
         new Thread(new Worker(i)).start();
      }
      waitUntilDone();
   }

   /**
    * 这个方法用来通知被Solver构造器调用的主线程不需要等待了/
    * 主线程在关联"abc"对象的监视器上等待.
    * "abc".notify() 这个调用足够唤醒仅在关联"abc"对象的监视器上等待的线程.
    */
   void mergeRows()
   {
      System.out.println("merging");
      synchronized("abc")
      {
         "abc".notify();
      }
   }

   void waitUntilDone()
   {
      synchronized("abc")
      {
         try
         {
            System.out.println("main thread waiting");
            "abc".wait();
            System.out.println("main thread notified");
         }
         catch (InterruptedException ie)
         {
            System.out.println("main thread interrupted");
         }
      }
   }
}